package com.fxu.framework.core.handler;

import cn.hutool.core.util.StrUtil;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import org.apache.ibatis.type.TypeHandler;
import org.jetbrains.annotations.NotNull;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 类型转换器，用于数据库的varchar和Java中List[Long]类型的相互转换
 * @author fangxu
 * @version 2022-01-06
 * 1、实体类上，需要加上注解 @TableName(autoResultMap = true)
 * 2、自定义TypeHandler类时，@MappedTypes({Object.class})是 不生效 的，还是指定 需要具体的type。
 *    比如List类型的字段可以自定义一个 ListTypeHandler（示例代码放在下面）
 * 3、自定义TypeHandler类需加注解：
 *  <p>@MappedJdbcTypes(JdbcType.VARCHAR) //数据库类型</p>
 *  <p>@MappedTypes({List.class}) //java数据类型</p>
 * 4、字段上需要注解标注：@TableField( typeHandler = ListTypeHandler.class)
 * 5、配置文件需要加上：mybatis-plus.type-handlers-package=com.package.handler（包名）
 */
@MappedTypes(List.class)
@MappedJdbcTypes(JdbcType.VARCHAR)
public class ListLongTypeHandler implements TypeHandler<List<Long>> {
    private static final String DOT = ",";

    @Override
    public void setParameter(PreparedStatement ps, int i, List<Long> vals, JdbcType jdbcType) throws SQLException {
        ps.setString(i, vals.stream().filter(Objects::nonNull).map(String::valueOf).collect(Collectors.joining(DOT)));
    }

    @Override
    public List<Long> getResult(@NotNull ResultSet resultSet, String columnName) throws SQLException {
        return getResult(resultSet.getString(columnName));
    }

    @Override
    public List<Long> getResult(ResultSet resultSet, int columnIndex) throws SQLException {
        return getResult(resultSet.getString(columnIndex));
    }

    @Override
    public List<Long> getResult(CallableStatement callableStatement, int columnIndex) throws SQLException {
        return getResult(callableStatement.getString(columnIndex));
    }

    public List<Long> getResult(String resultString) {
        if (StrUtil.isEmpty(resultString)) {
            return null;
        }
        return Arrays.stream(resultString.split(DOT)).map(Long::parseLong).collect(Collectors.toList());
    }
}